import dataCenter from './dataCenter';
import _ from 'lodash';

export const SET_INFO = 'SET_INFO';
export const UPDATE_DATA = 'UPDATE_DATA';
export const UPDATE_NODES_COUNT = 'UPDATE_NODES_COUNT';
export const UPDATE_RELATIONSHIPS_COUNT = 'UPDATE_RELATIONSHIPS_COUNT';
export const UPDATE_CURRENT_NODE_DETEAL = 'UPDATE_CURRENT_NODE_DETEAL';
export const UPDATE_RELATIONSHIPS = 'UPDATE_RELATIONSHIPS';
export const REMOVE_NODE = 'REMOVE_NODE';
export const ADD_NODE = 'ADD_NODE';
export const MAKE_CONNECT = 'MAKE_CONNECT';
export const DEL_CONNECT = 'DEL_CONNECT';
export const DEL_CONNECTS = 'DEL_CONNECTS';
export const DEL_NODE = 'DEL_NODE';
export const UPDATE_DETAIL = 'UPDATE_DETAIL';
export const MARK_SELECTED = 'MARK_SELECTED';
export const GET_DATASOURCE_LIST = 'GET_DATASOURCE_LIST';
export const CREATE_NODE = 'CREATE_NODE';
export const CREATE_INDEX = 'CREATE_INDEX';
export const CREATE_RELATIONSHIP = 'CREATE_RELATIONSHIP';
export const GET_TOPOLOGY = 'GET_TOPOLOGY';
export const SET_CURRENT_RELATION_EDITOR = 'SET_CURRENT_RELATION_EDITOR';
export const GET_LIST_NODES = 'GET_LIST_NODES';
export const GET_NODE = 'GET_NODE';
export const GET_LIST_RELATIONSHIPS = 'GET_LIST_RELATIONSHIPS';
export const GET_RELATION_BY_ID = 'GET_RELATION_BY_ID';
export const CLEAR = 'CLEAR';

function data2graph(rlt) {
	const data = {relationships: [], nodes: []};
	rlt.map(r => {
		r.data.map(d => {
			d.graph.nodes.map(i => data.nodes.push(i));
			d.graph.relationships.map(i => data.relationships.push(i));
		});
	});

	data.relationships = data.relationships.map(d => {
		  d.source = d.startNode;
		  d.target = d.endNode;
		  return d;
	});

	return data;
}

export function setInfo(value) {
	return {
		type: SET_INFO,
		info: value
	};
}

export function updateData(q, limit=20) {
	return dispatch => {
		dataCenter.getRelation({
				q: q,
				graph: 1,
				limit: limit
			})
			.then(rlt => {
				const data = data2graph(rlt);
			  dispatch({
			  	type: UPDATE_DATA,
			  	relationships: data.relationships,
			  	nodes: data.nodes,
			  })
			})
	}
} 

export function demo1(limit=20) {
	return dispatch => {
		dataCenter.getP2P({
				limit: limit
			})
			.then(rlt => {
				const data = data2graph(rlt);

			  dispatch({
			  	type: UPDATE_DATA,
			  	relationships: data.relationships,
			  	nodes: data.nodes,
			  })
			})
	}
} 

export function demo2(limit=20) {
	return dispatch => {
		dataCenter.getFlow({
				limit: limit
			})
			.then(rlt => {
				const data = data2graph(rlt);
			  dispatch({
			  	type: UPDATE_DATA,
			  	relationships: data.relationships,
			  	nodes: data.nodes,
			  })
			})
	}
}

export function demo3() {
	return dispatch => {
		dataCenter.getAllRelationTypes()
		.then(rlt => {
			const data = data2graph(rlt);
		  dispatch({
		  	type: UPDATE_DATA,
		  	relationships: data.relationships,
		  	nodes: data.nodes,
		  })
		})
	}
}

export function getAllNodesCount() {
	return dispatch => {
		dataCenter.getAllNodesCount()
		.then(rlt => {
		  dispatch({
		  	type: UPDATE_NODES_COUNT,
		  	nodesCount: rlt[0].data[0].row[0],
		  })
		})
	}
}

export function getAllRelationshipsCount() {
	return dispatch => {
		dataCenter.getAllRelationshipsCount()
		.then(rlt => {
		  dispatch({
		  	type: UPDATE_RELATIONSHIPS_COUNT,
		  	relationshipsCount: rlt[0].data[0].row[0],
		  })
		})
	}
}

export function demo5(nodeId) {
	return dispatch => {
		dataCenter.getNodeByNodeId(nodeId)
		.then(rlt => {
		  dispatch({
		  	type: UPDATE_CURRENT_NODE_DETEAL,
		  	currentNode: rlt && rlt.node || {},
		  	nodes: rlt && rlt.node && [Object.assign({id: rlt.node.metadata.id.toString(), labels: rlt.node.metadata.labels}, {properties: rlt.node.properties})] || []
		  })
		})
	}
}

export function demo6(nodeId) {
	return dispatch => {
		dataCenter.getRelationshipsByNodeId(nodeId)
		.then(rlt => {
			const relationships = rlt.relationships.map(item => Object.assign({endNode: item.endNode, target: item.endNode, source: item.startNode, startNode: item.startNode, properties: item.properties}, {id: item.metadata.id.toString(), type: item.metadata.type}));
		  let nodes = [];
		  relationships.map((item, index) => {
		  	let finalNodeId = '';
		  	if (item.startNode === nodeId) {
		  		finalNodeId = item.endNode;
		  	}
		  	if (item.endNode === nodeId) {
		  		finalNodeId = item.startNode;
		  	}
		  	dataCenter.getNodeByNodeId(finalNodeId)
	  		.then(rltInner => {
	  			nodes = [...nodes, Object.assign({id: rltInner.node.metadata.id.toString(), labels: rltInner.node.metadata.labels}, {properties: rltInner.node.properties})]
	  		})
	  		let jungleNodesNum = setInterval(function() {
	  			if (nodes.length === relationships.length) {
	  				clearInterval(jungleNodesNum);
	  				dispatch({
	  					type: 'UPDATE_RELATIONSHIPS',
	  					relationships: relationships,
	  					nodes: nodes
	  				})
	  			}
	  		}, 10)
		  })
		})
	}
}

export function removeNode(nodeId) {
	return dispatch => {
		dispatch({
			type: 'REMOVE_NODE',
			nodeId
		})
	}
}

export function getDirectedRelationByNodeId(nodeId, direction) {
	return dispatch => {
		dataCenter.getDirectedRelationByNodeId(nodeId, direction)
		.then(rlt => {
			const relationships = rlt.relationships.map(item => Object.assign({endNode: item.endNode, target: item.endNode, source: item.startNode, startNode: item.startNode, properties: item.properties}, {id: item.metadata.id.toString(), type: item.metadata.type}));
			let nodes = [];
			let nodesIdArray = relationships.reduce((pre, item, index) => {
				if (direction === 'all') {
					return _.uniq([...pre, item.startNode, item.endNode]);
				} else if (direction === 'in') {
					return _.uniq([...pre, item.startNode]);
				} else if (direction === 'out') {
					return _.uniq([...pre, item.endNode]);
				}
			}, [nodeId]);
			nodesIdArray.map((item, index) => {
		  	dataCenter.getNodeByNodeId(item)
	  		.then(rltInner => {
	  			nodes = [...nodes, Object.assign({id: rltInner.node.metadata.id.toString(), labels: rltInner.node.metadata.labels}, {properties: rltInner.node.properties})]
	  		})
	  		let jungleNodesNum = setInterval(function() {
	  			if (nodes.length === nodesIdArray.length) {
	  				clearInterval(jungleNodesNum);
	  				dispatch({
	  					type: 'UPDATE_RELATIONSHIPS',
	  					relationships: relationships,
	  					nodes: nodes
	  				})
	  			}
	  		}, 10)
		  })
		})
	}
}

export function searchRelations(q, limit=20) {
	return dispatch => {
		dataCenter.searchRelations({
			q: q,
			graph: 1,
			limit: limit
		}).then(rlt => {
			const data = data2graph(rlt);
		  dispatch({
		  	type: UPDATE_DATA,
		  	relationships: data.relationships,
		  	nodes: data.nodes,
		  })
		})
	}
}

export function advancedQueryNodes(data) {
	return dispatch => {
		dataCenter.advancedQueryNodes(data).then(rlt => {
			const data = data2graph(rlt);
		  dispatch({
		  	type: UPDATE_DATA,
		  	relationships: data.relationships,
		  	nodes: data.nodes,
		  })
		})
	}
}

export function advancedQueryRelationships(data) {
	return dispatch => {
		dataCenter.advancedQueryRelationships(data).then(rlt => {
			const data = data2graph(rlt);
		  dispatch({
		  	type: UPDATE_DATA,
		  	relationships: data.relationships,
		  	nodes: data.nodes,
		  })
		})
	}
}

export function advancedQueryPath(data) {
	return dispatch => {
		dataCenter.advancedQueryPath(data).then(rlt => {
			const data = data2graph(rlt);
		  dispatch({
		  	type: UPDATE_DATA,
		  	relationships: data.relationships,
		  	nodes: data.nodes,
		  })
		})
	}
}

export function getPaths(params) {
	return dispatch => {
		dataCenter.getPaths(params).then(rlt => {
			console.log('rlt: ', rlt);
			const data = data2graph(rlt);
		  dispatch({
		  	type: UPDATE_DATA,
		  	relationships: data.relationships,
		  	nodes: data.nodes,
		  })
		})
	}
}

export function addNode(value) {
	return {
		type: ADD_NODE,
		value
	};
}

export function makeConnect(value, id) {
	return {
		type: MAKE_CONNECT,
		value,
		id
	};
}

export function delConnect(value) {
	return {
		type: DEL_CONNECT,
		value
	};
}

export function delConnects(value) {
	return {
		type: DEL_CONNECTS,
		value
	};
}

export function delNode(id, componentType) {
	return {
		type: DEL_NODE,
		id,
		componentType
	};
}

export function updateDetail(componentType, changeDetail, componentId) {
	return {
		type: UPDATE_DETAIL,
		componentType,
		changeDetail,
		componentId
	};
}

export function markSelected(handleType, id) {
	return {
		type: MARK_SELECTED,
		handleType,
		id
	}
}

export function getDataSourceList(params) {
	return dispatch => {
		dataCenter.getDataSourceList(params).then(rlt => {
		  dispatch({
		  	type: GET_DATASOURCE_LIST,
		  	dataSourcelist: rlt
		  })
		})
	}
}

export function createNode(data, callback) {
	return dispatch => {
		dataCenter.createNode(data, callback).then(rlt => {
		  dispatch({
		  	type: CREATE_NODE,
		  	dealNodes: rlt,
		  	testCreateNodeResult: data
		  })
		})
	}
}

export function getListNodes(callback) {
	return dispatch => {
		dataCenter.getListNodes(callback).then(rlt => {
			dispatch({
				type: GET_LIST_NODES,
				createdNodesList: rlt.results
			})
		})
	}
}

export function getNode(id, callback) {
	return dispatch => {
		dataCenter.getNode(id, callback).then(rlt => {
			dispatch({
				type: GET_NODE,
				currentNode: rlt
			})
		})
	}
}

export function createRelationShip(data, callback) {
	return dispatch => {
		dataCenter.createRelationShip(data, callback).then(rlt => {
			dispatch({
				type: CREATE_RELATIONSHIP,
				testCreateRelationResult: data
			})
		})
	}
}

export function getListRelationships(data, callback) {
	return dispatch => {
		dataCenter.getListRelationships(data, callback).then(rlt => {
			dispatch({
				type: GET_LIST_RELATIONSHIPS,
				relationshipList: rlt.results
			})
		})
	}
}

export function getRelationById(id, callback) {
	return dispatch => {
		dataCenter.getRelationById(id, callback).then(rlt => {
			dispatch({
				type: GET_RELATION_BY_ID,
				currentRelation: rlt
			})
		})
	}
}

export function setCurrentRelationEditor(record) {
	return {
		type: SET_CURRENT_RELATION_EDITOR,
		record
	}
}

export function createIndex(data, callback) {
	return dispatch => {
		dataCenter.createIndex(data, callback).then(rlt => {
		  dispatch({
		  	type: CREATE_INDEX,
		  	dealNodes: rlt
		  })
		})
	}
}

export function getTopology() {
	return dispatch => {
		dataCenter.getTopology().then(rlt => {
		  dispatch({
		  	type: GET_TOPOLOGY,
		  	topology: rlt
		  })
		})
	}
}

export function clear() {
	return {
		type: 'CLEAR'
	}
}
